package List;

import jdk.internal.util.ArraysSupport;

import java.io.Serializable;
import java.util.*;

import static jdk.internal.util.ArraysSupport.newLength;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User:岁亮亮
 * Date:2024-05-15
 * TIME:16:26
 */
public class MyArrayList implements RandomAccess, Serializable,MyList{

    transient int[] elementData;

    private static final int DEFAULT_CAPACITY = 10;

    private static final int MAX_ARRAY_LENGTH = Integer.MAX_VALUE - 8;

    private int size;

    private int[] ELEMPTY_ARRAYLIST={};

    private int[] DEFAULT_ELEMPTY_ARRAYLIST={};

    MyArrayList(){
        this.elementData = DEFAULT_ELEMPTY_ARRAYLIST;
    }

    MyArrayList(int Initialcapacity){//初始化容量
        if(Initialcapacity > 0){
            this.elementData = new int[Initialcapacity];
        }
        else if(Initialcapacity == 0){
            this.elementData = ELEMPTY_ARRAYLIST;
        }
        else {
            throw new ArrayStoreException();
        }
    }

    @Override
    public void display() {
        for (int i = 0; i < this.size; i++) {
            System.out.println(elementData[i]);
        }
        System.out.println();
    }

    @Override
    public int elementDataLength() {
        return this.elementData.length;
    }

    @Override
    public int size() {
        return this.size;
    }

    @Override
    public boolean isEmpty() {
        return this.size == 0;
    }

    @Override
    public boolean isFull() {
        return this.size == this.elementData.length;
    }

    @Override
    public boolean contains(int n) {
        return indexOf(n) >= 0;
    }

    @Override
    public int indexOf(int n) {
        //Objects.checkIndex(n,elementData.length);
        if(this.size == 0){
            throw new NoSuchElementException();
        }
        for (int i = 0; i < size; i++) {
            if(this.elementData[i] == n){
                return i;
            }
        }
        return -1;

    }

    @Override
    public boolean add(int n) {
        //判断 数组容量是否满了 要扩容
        //添加及size++;
        checkCapacity();
        this.elementData[this.size++] = n;
        return true;
    }
    private void checkCapacity() {
        if(isFull()){
            this.elementData = grow();
        }
    }

    /**
     *两种扩容
     * 1.自动扩容
     * 2.指定容量 扩容
     */
    private int[] grow() {
        return grow(this.size + 1);
    }

    private int[] grow(int minCapacity){
        int oldCapacity = this.elementData.length;
        if(this.elementData == DEFAULT_ELEMPTY_ARRAYLIST && oldCapacity ==0){
           return this.elementData = new int[Math.max(DEFAULT_CAPACITY,minCapacity)];
        }
        else {
          //int newCapacity = ArraysSupport.newLength(oldCapacity,minCapacity - oldCapacity,oldCapacity>>1);
         int newCapacity = createNewLength(oldCapacity,minCapacity - oldCapacity,oldCapacity>>1);
           return this.elementData = Arrays.copyOf(elementData,newCapacity);
        }

    }

    private int createNewLength(int oldCapacity, int minGrowth, int preGrowth) {
       int newLength = oldCapacity + Math.max(minGrowth,preGrowth);
       if( newLength > 0 || newLength <= MAX_ARRAY_LENGTH){
           return newLength;
       }
       else {
           return hugeCapacity(oldCapacity,minGrowth);
       }
    }

    private int hugeCapacity(int oldCapacity, int minGrowth) {
        int hugeLength = oldCapacity + minGrowth;
        if(hugeLength < 0){/* 小于零的话说明长度超过int 表示的最大范围   overflow*/
            throw new OutOfMemoryError();
        }
        else if(minGrowth <= MAX_ARRAY_LENGTH){
            return MAX_ARRAY_LENGTH;
        }
        else {
            return hugeLength;
        }
    }


    /**
     * 1.先判断 下标是否越界
     * 2.检查容量
     * 2.将下标index到最后的下标向后 移动一位
     * 3.添加元素
     */
    @Override
    public void add(int index, int n) {

        checkIndexForAdd(index);
        checkCapacity();
        System.arraycopy(elementData,index,elementData,index+1,this.size - index);
        this.elementData[index] = n;
        this.size++;



    }

    private void checkIndexForAdd(int index) {
        if(index<0 || index > size){
            throw new IllegalArrayIndexException("数组下标越界异常 " + index);
        }
    }

    @Override
    public boolean addAll(int[] array) {
        if( array == null){
            throw new NullPointerException();
        }
        if(array.length == 0){
            return false;
        }
        int elementLength = this.elementData.length;
        int minCapacity;
        if(elementLength < (minCapacity=(this.size + array.length))){
            this.elementData = grow(minCapacity);
        }
        System.arraycopy(array,0,elementLength,size,array.length);
        this.size = this.size + array.length;
        return true;
    }

    /***
     *1.首先检查下标是否越界
     *2.判断数组是否为空和长度是否为零
     * 3.检查添加之后是否要进行扩容;
     * 4.移动下标index及以后的位置向后移动一位
     * 5.更新size
     */
    @Override
    public boolean addAll(int index, int[] array) {
        checkIndexForAdd(index);
        if( array == null){
            throw new NullPointerException();
        }
        if( array.length == 0){
            return false;
        }
        int minCapacity;
        if( this.elementData.length < (minCapacity = ( this.size + array.length))){
            this.elementData = grow(minCapacity);
        }
        int numMoved = this.size - index;
        if( numMoved > 0){
            System.arraycopy(this.elementData,index,elementData,index + array.length,numMoved);
        }
        System.arraycopy(array,0,elementData,index,array.length);
        this.size = this.size + array.length;
        return true;

    }

    @Override
    public boolean addFirst(int n) {
        checkCapacity();
        System.arraycopy(elementData,0,elementData,1,size);
        elementData[0] = n;
        size++;
        return true;

    }

    private void fastRemove(int index){
        if(this.elementData.length == 0){
            throw new NoSuchElementException();
        }
        int numRemove = this.size - index -1;
        if(numRemove > 0){
            System.arraycopy(elementData,index + 1,elementData,index,numRemove);
        }
        this.elementData[--this.size] = 00;
    }


    @Override
    public int remove(int index) {
        if(this.elementData.length == 0){
            throw new NoSuchElementException();
        }
        Objects.checkIndex(index,this.size);
        int oldElement = this.elementData[index];
        fastRemove(index);
        return oldElement;
    }

    @Override
    public int set(int index, int n) {
        Objects.checkIndex(index,this.size);
        int oldElement = this.elementData[index];
        this.elementData[index] = n;
        return oldElement;
    }

    @Override
    public int get(int index) {
        Objects.checkIndex(index,this.size);
        if(this.size == 0){
            throw new NoSuchElementException();
        }
        int getElement = this.elementData[index];
        return getElement;
    }
}
